// combineMetalBalance.js
import { SelfDefFundAccountType } from "../funds/selfDefFundAccountType"
import { CsDouble } from '../common/csDouble.js';
import { Util } from "../../utils/util.js";
import { CombineOrderType } from '../common/docDefinition.js';

export class CombineMetalBalance {
    _id = null;   // id
    _metalFundType = null;      // SelfDefFundAccountType
    _subCommodityId = null;
    _inCount = null;  // 收
    _outCount = null;  // 支出
    _inExpectCount = null;  // 应收
    _outExpectCount = null; // 应付

    _balanceBefore = CsDouble.zero();  // 本次记录后前总账余额
    _balanceAfter = CsDouble.zero();  // 本次记录后总账余额

    _innerBalance = CsDouble.zero();  // 内部总账余额(前端编辑不更新该值，fromJson时 后台赋值，用于汇总显示)

    // Constructor
    constructor(
        { id, metalFundType, subCommodityId,
            inCount,
            outCount,
            inExpectCount,
            outExpectCount,
            balanceBefore,
            balanceAfter,
            innerBalance
        } = {}) {
        this._id = id;
        this._metalFundType = metalFundType;
        this._subCommodityId = subCommodityId;
        this._inCount = inCount;
        this._outCount = outCount;
        this._inExpectCount = inExpectCount;
        this._outExpectCount = outExpectCount;
        this._balanceBefore = balanceBefore || CsDouble.zero();
        this._balanceAfter = balanceAfter || CsDouble.zero();
        this._innerBalance = innerBalance ?? CsDouble.zero();
    }

    // Getters and setters
    get id() {
        return this._id;
    }

    set id(value) {
        this._id = value;
    }

    get metalFundType() {
        return this._metalFundType;
    }

    set metalFundType(value) {
        this._metalFundType = value;
    }

    get subCommodityId() {
        return this._subCommodityId;
    }

    set subCommodityId(value) {
        this._subCommodityId = value;
    }

    get inCount() {
        return this._inCount;
    }

    set inCount(value) {
        this._inCount = value;
        this.updateBalanceAfter();
    }

    get outCount() {
        return this._outCount;
    }

    set outCount(value) {
        this._outCount = value;
        this.updateBalanceAfter();
    }

    get inExpectCount() {
        return this._inExpectCount;
    }

    set inExpectCount(value) {
        this._inExpectCount = value;
        this.updateBalanceAfter();
    }

    get outExpectCount() {
        return this._outExpectCount;
    }

    set outExpectCount(value) {
        this._outExpectCount = value;
        this.updateBalanceAfter();
    }

    get balanceBefore() {
        return this._balanceBefore;
    }

    setBalanceBefore(value, combineOrder) {

        if (combineOrder.combineOrderType.code === CombineOrderType.PeriodInitalRnd.code
            || combineOrder.combineOrderType.code === CombineOrderType.SettledRnd.code) {
                  console.log("set balanceBefore value for PeriodInitalRnd record");
            this._balanceAfter = this.innerBalance ?? CsDouble.zero();
            return;
        }

        if (value == null) {
            //   console.log("set balanceBefore value is null");
            return;
        }
        this._balanceBefore = value;
        this.updateBalanceAfter();
    }

    get balanceAfter() {
        return this._balanceAfter;
    }

    // set balanceAfter(value) {
    //     this._balanceAfter = value;
    // }

    // 获取收和应收盈余 = 收 - 应收 (客户视角)
    // = 0 表示收和应收没有盈余
    // < 0 表示对方欠款
    // > 0 示对方有盈余
    get inBalance() {
        if (this._inCount != null || this._inExpectCount != null) {
            let inExpectCount = this._inExpectCount ?? CsDouble.zero();
            let inCount = this._inCount ?? CsDouble.zero();
            return inCount.sub(inExpectCount);
        }
        return null;
    }

    // 获取付和应付盈余 = 付 - 应付 (客户视角)
    // = 0 示付和应付没有盈余
    // < 0 示对方欠款
    // > 0 示对方有盈余
    get outBalance() {
        if (this._outCount != null || this._outExpectCount != null) {
            let outExpectCount = this._outExpectCount ?? CsDouble.zero();
            let outCount = this._outCount ?? CsDouble.zero();
            return outExpectCount.sub(outCount);
        }
        return null;
    }

    get innerBalance() {
        return this._innerBalance;
    }

    // 期初单据调用
    set innerBalance(value) {
        this._innerBalance = value;
        this._balanceAfter = value;
    }

    // 更新总账 = 前总账 + 收盈余 + 付盈余 (均为客户视角，正数客户盈余)
    updateBalanceAfter() {
        if (this._balanceBefore != null || this.inBalance != null || this.outBalance != null) {
            let balanceBefore = this._balanceBefore ?? CsDouble.zero();
            let inBalance = this.inBalance ?? CsDouble.zero();
            let outBalance = this.outBalance ?? CsDouble.zero();
            // 总账 = 前总账 + 收盈余 + 付盈余 (均为客户视角，正数客户盈余)
            this._balanceAfter = balanceBefore.add(inBalance).add(outBalance);
        }
    }


    // 克隆方法
    static clone(unit) {
        return new CombineMetalBalance(
            {
                id: unit._id,
                metalFundType: SelfDefFundAccountType.clone(unit._metalFundType),
                subCommodityId: unit._subCommodityId,

                inCount: unit._inCount ? new CsDouble(unit._inCount.value) : null,
                outCount: unit._outCount ? new CsDouble(unit._outCount.value) : null,
                inExpectCount: unit._inExpectCount ? new CsDouble(unit._inExpectCount.value) : null,
                outExpectCount: unit._outExpectCount ? new CsDouble(unit._outExpectCount.value) : null,
                balanceBefore: unit._balanceBefore ? new CsDouble(unit._balanceBefore.value) : null,
                balanceAfter: unit._balanceAfter ? new CsDouble(unit._balanceAfter.value) : null,
                innerBalance: unit._innerBalance ? new CsDouble(unit._innerBalance.value) : null,
            }
        );
    }

    // From JSON method
    static fromJson(json) {
        return new CombineMetalBalance(
            {
                id: Util.jsonToString(json.id),
                metalFundType: json.metalFundTypeId ? new SelfDefFundAccountType(json.metalFundTypeId) : null,
                subCommodityId: Util.jsonToString(json.specId),

                inCount: Util.jsonToCsDouble(json.inCount, null),
                outCount: Util.jsonToCsDouble(json.outCount, null),
                inExpectCount: Util.jsonToCsDouble(json.inExpect, null),
                outExpectCount: Util.jsonToCsDouble(json.outExpect, null),
                balanceBefore: null,
                balanceAfter: null,
                innerBalance: Util.jsonToCsDouble(json['innerBalance'], null),
            }
        );
    }

    // To JSON for transition method
    toJson(innerBalanceDirect = false) {
        let ret = {
            id: this._id,
            subCommodityId: this._subCommodityId
        };

        if (this._metalFundType) {
            ret.metalFundTypeId = this._metalFundType.id;
        }

        if (this._inCount != null) {
            ret.inCount = this._inCount.value;
        }

        if (this._outCount != null) {
            ret.outCount = this._outCount.value;
        }

        if (this._inExpectCount != null) {
            ret.inExpect = this._inExpectCount.value;
        }

        if (this._outExpectCount != null) {
            ret.outExpect = this._outExpectCount.value;
        }

        if (innerBalanceDirect) {
            ret.innerBalance = this._innerBalance?.value ?? 0;
        }
        else {
            let inBalance = this.inBalance ?? CsDouble.zero();
            let outBalance = this.outBalance ?? CsDouble.zero();

            ret.innerBalance = inBalance.add(outBalance).value;
        }

        return ret;
    }
}